﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dokan;
using System.IO;
using System.Collections;
using System.Diagnostics;

namespace CueMounter.DokanStructure
{
	public class DokanOperationsDebugProxy : DokanOperations
	{
		public DokanOperations Operations { get; private set; }

		public DokanOperationsDebugProxy(DokanOperations operations)
		{
			Operations = operations;
		}

		private void Log(string message)
		{
			Debug.WriteLine(message);
		}

		private void LogReturn(int result)
		{
			Log("Return: " + result);
		}

		private int OnThrow(Exception e)
		{
			Log("Thrown " + e);
			return DokanNet.DOKAN_ERROR;
		}

		public int Cleanup(string filename, DokanFileInfo info)
		{
			Log("Cleanup(" + filename + ")");
			try
			{
				int result = Operations.Cleanup(filename, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int CloseFile(string filename, DokanFileInfo info)
		{
			Log("CloseFile(" + filename + ")");
			try
			{
				int result = Operations.CloseFile(filename, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int CreateDirectory(string filename, DokanFileInfo info)
		{
			Log("CreateDirectory(" + filename + ")");
			try
			{
				int result = Operations.CreateDirectory(filename, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int CreateFile(string filename, FileAccess access, FileShare share, FileMode mode, FileOptions options, DokanFileInfo info)
		{
			Log("CreateFile(" + filename + ", " + access + ", " + share + ", " + mode + ", " + options + ")");
			try
			{
				int result = Operations.CreateFile(filename, access, share, mode, options, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int DeleteDirectory(string filename, DokanFileInfo info)
		{
			Log("DeleteDirectory(" + filename + ")");
			try
			{
				int result = Operations.DeleteDirectory(filename, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int DeleteFile(string filename, DokanFileInfo info)
		{
			Log("DeleteFile(" + filename + ")");
			try
			{
				int result = Operations.DeleteFile(filename, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int FindFiles(string filename, ArrayList files, DokanFileInfo info)
		{
			Log("FindFiles(" + filename + ", files)");
			try
			{
				int result = Operations.FindFiles(filename, files, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int FlushFileBuffers(string filename, DokanFileInfo info)
		{
			Log("FlushFileBuffers(" + filename + ")");
			try
			{
				int result = Operations.FlushFileBuffers(filename, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int GetDiskFreeSpace(ref ulong freeBytesAvailable, ref ulong totalBytes, ref ulong totalFreeBytes, DokanFileInfo info)
		{
			Log("GetDiskFreeSpace()");
			try
			{
				int result = Operations.GetDiskFreeSpace(ref freeBytesAvailable, ref totalBytes, ref totalFreeBytes, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int GetFileInformation(string filename, FileInformation fileinfo, DokanFileInfo info)
		{
			Log("GetFileInformation(" + filename + ")");
			try
			{
				int result = Operations.GetFileInformation(filename, fileinfo, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int LockFile(string filename, long offset, long length, DokanFileInfo info)
		{
			Log("LockFile(" + filename + ", " + offset + ", " + length + ")");
			try
			{
				int result = Operations.LockFile(filename, offset, length, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int MoveFile(string filename, string newname, bool replace, DokanFileInfo info)
		{
			Log("MoveFile(" + filename + ", " + newname + ", " + replace + ")");
			try
			{
				int result = Operations.MoveFile(filename, newname, replace, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int OpenDirectory(string filename, DokanFileInfo info)
		{
			Log("OpenDirectory(" + filename + ")");
			try
			{
				int result = Operations.OpenDirectory(filename, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int ReadFile(string filename, byte[] buffer, ref uint readBytes, long offset, DokanFileInfo info)
		{
			Log("ReadFile(" + filename + ", byte[" + buffer.Length + "], ref readBytes, " + offset + ")");
			try
			{
				int result = Operations.ReadFile(filename, buffer, ref readBytes, offset, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int SetAllocationSize(string filename, long length, DokanFileInfo info)
		{
			Log("SetAllocationSize(" + filename + ", " + length + ")");
			try
			{
				int result = Operations.SetAllocationSize(filename, length, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int SetEndOfFile(string filename, long length, DokanFileInfo info)
		{
			Log("SetEndOfFile(" + filename + ", " + length + ")");
			try
			{
				int result = Operations.SetEndOfFile(filename, length, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int SetFileAttributes(string filename, FileAttributes attr, DokanFileInfo info)
		{
			Log("SetFileAttributes(" + filename + ", " + attr + ")");
			try
			{
				int result = Operations.SetFileAttributes(filename, attr, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int SetFileTime(string filename, DateTime ctime, DateTime atime, DateTime mtime, DokanFileInfo info)
		{
			Log("SetFileTime(" + filename + ", " + ctime + ", " + atime + ", " + mtime + ")");
			try
			{
				int result = Operations.SetFileTime(filename, ctime, atime, mtime, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int UnlockFile(string filename, long offset, long length, DokanFileInfo info)
		{
			Log("UnlockFile(" + filename + ", " + offset + ", " + length + ")");
			try
			{
				int result = Operations.UnlockFile(filename, offset, length, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int Unmount(DokanFileInfo info)
		{
			Log("Unmount()");
			try
			{
				int result = Operations.Unmount(info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}

		public int WriteFile(string filename, byte[] buffer, ref uint writtenBytes, long offset, DokanFileInfo info)
		{
			Log("WriteFile(" + filename + ", byte[" + buffer.Length + "], ref writtenBytes, " + offset + ")");
			try
			{
				int result = Operations.WriteFile(filename, buffer, ref writtenBytes, offset, info);
				LogReturn(result);
				return result;
			}
			catch(Exception e)
			{
				return OnThrow(e);
			}
		}
	}
}
